import WallGradientMaterialProperty from '../WallGradientMaterialProperty'
import * as Cesium from 'cesium'
// 飞行到指定线路
export const flyToLine = (viewer, name) => {
  const targetEnt = lines.find((item) => item.name === name)
  if (!targetEnt) {
    return
  }
  // 注意：如果lines是ref响应式的proxy，则飞不了
  viewer.flyTo(targetEnt)
}

// 添加圆柱
const cones = []
export const addGradientCone = (viewer, options) => {
  // 圆柱颜色
  const wallColor = Cesium.defaultValue(
    new Cesium.Color.fromCssColorString(options.color),
    Cesium.Color.AQUA
  )
  const name = Cesium.defaultValue(options.name, '')
  // 坐标中心，经纬度
  const center = Cesium.defaultValue(options.position, {
    lng: 0,
    lat: 0,
    height: 0,
  })

  const wallHeight = Cesium.defaultValue(options.height, 5000)
  const baseHeight = Cesium.defaultValue(options.baseHeight, 0)
  const radius = Cesium.defaultValue(options.radius, 400)
  // 得到圆柱的顶点坐标
  const positions = generateCircleCoordinates([center.lng, center.lat], radius)
  // 将经纬度转为笛卡尔3
  const wallPositions = pointsToPositions(positions, baseHeight)
  let minimumHeights = [] //最小高度集合
  let maximumHeights = [] //最大高度集合
  wallPositions.forEach((position) => {
    minimumHeights.push(baseHeight)
    maximumHeights.push(baseHeight + wallHeight)
  })
  const cone = viewer.entities.add({
    name,
    center: new Cesium.Cartesian3.fromDegrees(
      center.lng,
      center.lat,
      baseHeight
    ),
    wall: {
      positions: wallPositions,
      minimumHeights: minimumHeights,
      maximumHeights: maximumHeights,
      material: new WallGradientMaterialProperty(wallColor),
      // material: new Cesium.Color.fromCssColorString(options.color),
    },
  })
  cones.push(cone)
}

// 生成圆的坐标点
function generateCircleCoordinates(center, radius, numPoints = 360) {
  const earthRadius = 6371000 // 地球平均半径，单位：米
  const lat = center[1] // 中心点纬度
  const lng = center[0] // 中心点经度
  const points = []
  for (let i = 0; i < numPoints; i++) {
    const radians = Cesium.Math.toRadians(i) // 将角度转换为弧度
    // 纬度变化（单位：度）
    const deltaLat =
      ((radius * Math.sin(radians)) / earthRadius) * (180 / Math.PI)
    // 经度变化（单位：度）
    const deltaLng =
      ((radius * Math.cos(radians)) /
        (earthRadius * Math.cos(Cesium.Math.toRadians(lat)))) *
      (180 / Math.PI)
    const pointLat = lat + deltaLat // 计算新的纬度
    const pointLng = lng + deltaLng // 计算新的经度
    points.push([pointLng, pointLat]) // 将新的点存入数组
  }
  return points
}

// 将经纬度转为笛卡尔3
function pointsToPositions(positions, baseHeight) {
  const cartesianPositions = []
  positions.forEach((position) => {
    const cartesian = Cesium.Cartesian3.fromDegrees(
      position[0],
      position[1],
      position[2]
    )
    cartesianPositions.push(cartesian)
  })
  return cartesianPositions
}

// 删除所有圆柱
export const removeAllCones = (viewer) => {
  cones.forEach((cone) => {
    cone && viewer.entities.remove(cone)
  })
  cones.length = 0
}

// 根据线路名称闪烁线路
let timerBink
let lastActiveRoute
export const binkLineByName = (name) => {
  const targetEnt = lines.find((item) => item.name === name)
  if (!targetEnt) {
    return
  }
  // 如果选中的是刚刚高亮的，判断是否存在定时器，存在的话，就返回
  if (timerBink && name === lastActiveRoute) {
    return
  }

  // 如果选中的不是刚刚高亮的，直接清除定时器，然后高亮
  if (name !== lastActiveRoute && timerBink) {
    window.clearInterval(timerBink)
    timerBink = null
    lastActiveEnt.polyline.material.glowPower = 0.12
  }

  const originGlowPower = targetEnt.polyline.material.glowPower

  const timeBreak = 600
  let binkCount = 6
  let count = 0

  timerBink = setInterval(() => {
    if (count >= binkCount) {
      window.clearInterval(timerBink)
      timerBink = null
    } else {
      let isBink = count % 2 === 0
      targetEnt.polyline.material.glowPower = isBink
        ? originGlowPower * 4
        : originGlowPower
      count++
    }
  }, timeBreak)
}

// 🟢光锥
/**
 * 
 * @param {Cesium.Viewer} viewer 
 * @param {*} options 
 * @returns 
 */
export const coneWithLight = (viewer, options) => {
  const position=Cesium.defaultValue(options.position, Cesium.Cartesian3.ZERO);
  const height=Cesium.defaultValue(options.height, 700);
  const bottomRadius=Cesium.defaultValue(options.bottomRadius, 100);
  const color=Cesium.defaultValue(options.color, Cesium.Color.AQUA);
  const modelMatrix = Cesium.Matrix4.multiplyByTranslation(
      Cesium.Transforms.eastNorthUpToFixedFrame(position),
      new Cesium.Cartesian3(0.0, 0.0, height * 0.5), new Cesium.Matrix4()
  );

  const cylinderGeometry = new Cesium.CylinderGeometry({
      length: height,
      topRadius: 0.0,
      bottomRadius: bottomRadius * 0.7,
      vertexFormat: Cesium.MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat
  });

  const cone = new Cesium.GeometryInstance({
      geometry: cylinderGeometry,
      modelMatrix: modelMatrix,
  });

  return viewer.scene.primitives.add(new Cesium.Primitive({
      geometryInstances: [cone],
      appearance: new Cesium.MaterialAppearance({
          material: new Cesium.Material({
              fabric: {
                  type: 'VtxfShader1',
                  uniforms: {
                      color: color
                  },
                  source: /*glsl*/`
                          uniform vec4 color;   
                          czm_material czm_getMaterial(czm_materialInput materialInput)
                          {
                              czm_material material = czm_getDefaultMaterial(materialInput);
                              vec2 st = materialInput.st;
                              float time=fract(czm_frameNumber/10.0);
                              float isAlpha=step(0.5,time);
                              float dis = distance(st, vec2(0.5)); 
                              material.diffuse =1.9 * color.rgb;
                              if(isAlpha>=1.0){
                                  material.alpha = color.a * dis *2.0;
                              }else{
                                  material.alpha = color.a * dis *1.5;
                              }

                              return material;
                          }
                      `
              },
              translucent: false
          }),
          faceForward: false, // 当绘制的三角面片法向不能朝向视点时，自动翻转法向，从而避免法向计算后发黑等问题
          closed: true // 是否为封闭体，实际上执行的是是否进行背面裁剪
      })
  }));
}

// 🟢站点底部圆环
import ConeGlowBottomCircleMaterialProperty from "./ConeGlowBottomCircleMaterialProperty";
export const bottomCircle = (viewer, options) => {
    const position = Cesium.defaultValue(
        options.position,
        Cesium.Cartesian3.ZERO
    );
    const color = Cesium.defaultValue(options.color, Cesium.Color.AQUA);
    const bottomRadius = Cesium.defaultValue(options.bottomRadius, 100);
    return viewer.entities.add({
        position: position,
        ellipse: {
            semiMinorAxis: bottomRadius * 2,
            semiMajorAxis: bottomRadius * 2,
            height: 0.0,
            material: new ConeGlowBottomCircleMaterialProperty(color),
        },
    });
};

// 🟢站点和道路线
// 渲染站点  传入颜色十六进制字符串，名称，位置{lng,lat,height}
const stations = [];
export const renderStation = (viewer, options) => {
    const position = Cesium.defaultValue(options.positions, {
        lng: 0,
        lat: 0,
    });
    const positionCar3 = Cesium.Cartesian3.fromDegrees(
        position.lng,
        position.lat,
    );
    // 光锥
    const conePrimitve = coneWithLight(viewer, {
        position: positionCar3,
        height: 700,
        bottomRadius: 100,
        color: Cesium.Color.fromCssColorString(options.color),
    });

    // 底部圆环
    const bottomCircleEntity = bottomCircle(viewer, {
        position: positionCar3,
        bottomRadius: 100,
        color: Cesium.Color.fromCssColorString(options.color),
    });
    const target = {
        conePrimitve,
        bottomCircleEntity,
        name: options.name,
    };
    stations.push(target);
    return target;
};

// 删除单个站点，直接删除，而不是隐藏
export const removeStationByName = (viewer, name) => {
    const target = stations.find((item) => item.name === name);
    if (target) {
        const { conePrimitve, bottomCircleEntity } = target;
        viewer.scene.primitives.remove(conePrimitve);
        viewer.entities.remove(bottomCircleEntity);
        stations.splice(stations.indexOf(target), 1);
    }
};

// 删除所有站点
export const removeAllStations = (viewer) => {
    stations.forEach((item) => {
        const { conePrimitve, bottomCircleEntity } = item;
        viewer.scene.primitives.remove(conePrimitve);
        viewer.entities.remove(bottomCircleEntity);
    });
    stations.length = 0;
};

// 通过名称Array控制站点显示隐藏
export const hideStationByName = (names, isShow) => {
  //indexOf() 方法：返回元素在数组中第一次出现的索引 ,如果找到返回索引值（0或正整数）
  const targets = stations.filter((item) => names.indexOf(item.name) > -1)
  if (targets.length) {
    targets.forEach((target) => {
      const { conePrimitve, bottomCircleEntity } = target
      conePrimitve.show = isShow
      bottomCircleEntity.show = isShow
    })
  }
}

/* 🟢🟢🟢隐藏站点和线路 */
// 通过名称整体控制显示隐藏

// 
export const displayAll = (viewer,isShow) => {
    stations.forEach((item) => {
        const { conePrimitve, bottomCircleEntity } = item;
        conePrimitve.show = isShow;
        bottomCircleEntity.show = isShow;
    });
    lines.forEach((line) => {
        line.show = isShow;
    });
    billboards.forEach((item) => {
        const { billboard, billControler } = item;
        billControler.isDisplay = isShow;
        billboard.style.display = isShow ? "block" : "none";
    });
};

export const displayByName = (
  lineNames,
  stationNames,
  billboardsNames,
  isShow
) => {
  hideLineByName(lineNames, isShow)
  hideStationByName(stationNames, isShow)
  hideBillboardsByName(billboardsNames, isShow)
}

// 创建地铁线路 positions:[{lng,lat,height}]
// color:十六进制颜色字符串
// name:线路名称
const lines = [];
export const renderLines = (viewer, options) => {
    const positions = Cesium.defaultValue(options.positions, [
        {
            lng: 0,
            lat: 0,
        },
    ]);
    const color = Cesium.defaultValue(options.color, Cesium.Color.AQUA);
    const name = Cesium.defaultValue(options.name, "line");
    const positionRes = Cesium.Cartesian3.fromDegreesArray(positions);
    const lineEnt = viewer.entities.add({
        name,
        polyline: {
            positions: positionRes,
            width: 20,
            //使用cesium默认的泛光线
            material: new Cesium.PolylineGlowMaterialProperty({
                color: color,
                glowPower: 0.12,
            }),
        },
    });
    lines.push(lineEnt);
    return lineEnt;
};

// 删除地铁线路，不是隐藏
export const removeAllLines = (viewer) => {
    lines.forEach((line) => {
        line && viewer.entities.remove(line);
    });
};

// 🟢通过名称控制线路显示隐藏
export const hideLineByName = (names, isShow) => {
    lines.forEach((line) => {
        if (names.indexOf(line.name) > -1) {
            line.show = isShow;
        }
    });
};

// 🟢渲染全部站点和线路
/* maximumVertexTextureImageUnits 为 undefined 表明你的设备或浏览器的 WebGL 环境不支持顶点纹理。
让我们修改渲染方法，使用更基础的渲染方式： */
export const renderAll = (viewer, dataSource, isCache = true) => {
  const cacheData = {
    lineEnts: [],
    stationEnts: [],
    billboards: [],
  }

  try {
    if (!dataSource?.length) return;
    dataSource.forEach((item) => {
      // 渲染线路
      const { paths, name, color, stationsList } = item;
      const position = [];
      paths.forEach((path) => {
        position.push(path.lng, path.lat); //需要展开
      });
      // console.log(position);
      renderLines(viewer, {
        positions: position,
        color: new Cesium.Color.fromCssColorString(color),
        name,
        isCache,
      })
      !isCache && cacheData.lineEnts.push(lineEnt)
      // 渲染站点
      // console.log(stationsList[0].name);
      stationsList.forEach((station) => {
        const { position, name } = station;
        renderStation(viewer, {
          positions: position,
          name,
          color,
          isCache,
        })
        !isCache && cacheData.stationEnts.push(stationEnt)
        // 添加站点标牌
        renderStationBill(viewer, {
          position,
          name,
          color,
          height: 900, // 可以根据需要调整标牌高度
          show: true,
          attr: station, // 传入站点的完整属性数据
          isCache,
        })
        !isCache && cacheData.billboards.push(billboard)
      })
    })
    return cacheData
  } catch (error) {
    console.error('Error in renderAll:', error)
  }
};

// 清除全部
export const removeAll = (viewer) => {
    removeAllLines(viewer);
    removeAllStations(viewer);
};

// 🟢站点的标牌
const billboards = [];
import SimpleLabel from "../Bubble/htmlMarker";
// 渲染站点标牌，后期还要添加点击查询功能
export const renderStationBill = async (viewer, options) => {
    const position = Cesium.defaultValue(options.position, {
        lng: 0,
        lat: 0,
    });
    const height = Cesium.defaultValue(options.height, 200);
    const name = Cesium.defaultValue(options.name, "站点");
    const show = Cesium.defaultValue(options.show, true);
    const color = Cesium.defaultValue(options.color, "#ff0000");
    const attr = Cesium.defaultValue(options.attr, {});
    const isCache = Cesium.defaultValue(options.isCache, true);
    /* 使用 htmlMarker.js中的 SimpleLabel类 */
    const billControler = new SimpleLabel(viewer, {
        position: Cesium.Cartesian3.fromDegrees(
            position.lng,
            position.lat,
            height
        ),
        label: name,
        isShow: show,
        color: color,
        // 调整标牌大小：
        // 近处(1000米)时大小为2
        // 远处(20000米)时大小为0.8
        scaleByDistance: new Cesium.NearFarScalar(1000, 2, 20000, 0.8),
        attr: attr,
        type: "marker",
    });
    await billControler.addLabel();

    const target = {
        billControler,
        billboard: billControler.vmInstance.el,
        name,
    };
    isCache && billboards.push(target);
    return target;
};

// 🟢隐藏所有标牌
export const hideBillboardsByName = (names, isShow) => {
  billboards.forEach((item) => {
    if (names.indexOf(item.name) > -1) {
      // 使用 billControler 来控制显示/隐藏
      const { billboard, billControler } = item
      billControler.isDisplay = isShow
      billboard.style.display = isShow ? 'block' : 'none'
    }
  })
}

// 清除所有站点标牌
export const removeAllBillboards = () => {
    billboards.forEach((item) => {
        const { billControler } = item;
        billControler.removeMarker();
        billControler.queryPopup && billControler.removeQueryPopup();
    });
};

// 按照缓存数据清除
// cacheData类型 {
//   lineEnts:[],
//   stationEnts:[],
//   billboards:[{
//     billControler:SimpleLabel实例,
//     billboard:Billboard实例
//}]
// }
export const removeByCacheData = (viewer, cacheData) => {
  if (Object.keys(cacheData).length === 0) {
    return
  }
  const { lineEnts, stationEnts, billboards } = cacheData

  lineEnts.forEach((line) => viewer.entities.remove(line))
  stationEnts.forEach((station) => {
    const { conePrimitve, bottomCircleEntity } = station
    viewer.scene.primitives.remove(conePrimitve)
    viewer.entities.remove(bottomCircleEntity)
  })
  billboards.forEach((item) => {
    const { billControler } = item
    billControler.removeMarker()
   billControler.removeQueryPopup()
  })
  removeAllBillboards()
}

// 根据名称Array控制站点标牌显示与隐藏
export const changeDisplayBillBoard = (names, isShow) => {
    const filterBills = billboards.filter(
        (item) => names.indexOf(item.billControler.label) > -1
    );
    filterBills.forEach((item) => {
        const { billboard, billControler } = item;
        billControler.isDisplay = isShow;
        billboard.style.display = isShow ? "block" : "none";
    });
};

// 渲染热力图,传入站点坐标，站点信息，渲染热力图
// dataSource Array<{
//  lng,lat,value
//}>
import getCesiumHeat from "../cesiumHeatMap";
// getCesiumHeat是一个函数
export const renderHeat = (viewer, dataSource) => {
    // CesiumHeat是一个类
    const CesiumHeat = getCesiumHeat(Cesium);
    // heat是一个对象
    let heat = new CesiumHeat(
        viewer,
        {
            autoMaxMin: true,
            // data list, each has x, y, and value | 数据数组，每个包含 x,y,value字段
            data: dataSource,
        },
        // bbox for heatmap | 只在范围内显示热力图拉近会清晰些，默认整个地球但拉近后巨模糊
        [114.03, 30.2, 114.45, 30.9]
    );

    const destroyHeat = () => {
        heat.destory();
    };
    // 将清除方法暴露出去
    return destroyHeat;
};
// 视角飞到全局
export const flyToDefaultView = (viewer) => {
  viewer.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(113.95, 30.19, 34000),
    duration: 2,
    orientation: {
      heading: Cesium.Math.toRadians(35.0),
      pitch: Cesium.Math.toRadians(-37.0),
      roll: 0.0,
    },
  })
}


// 按照站点名称聚焦
export const focusOnStation = (viewer, stationName, cacheData) => {
    let targetData = stations;
    if (cacheData) {
        targetData = cacheData.stationEnts;
    }
    const target = targetData.find(
        (item) => item.name === stationName
    );
    if (!target) {
        message.error(`找不到站点${stationName}`);
        return;
    }
    const { bottomCircleEntity } = target;
    //设置相机视角
    bottomCircleEntity &&
        viewer.flyTo(bottomCircleEntity, {
            offset: new Cesium.HeadingPitchRange(
                Cesium.Math.toRadians(30),
                Cesium.Math.toRadians(-45),
                3000
            ),
        });
};